package com.yhsoft.buyer.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.wxpay.sdk.WXPayUtil;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.yhsoft.buyer.entity.BuyerOrder;
import com.yhsoft.buyer.entity.BuyerPayment;
import com.yhsoft.buyer.entity.BuyerUser;
import com.yhsoft.buyer.mapper.BuyerPaymentMapper;
import com.yhsoft.buyer.service.IBuyerOrderService;
import com.yhsoft.buyer.service.IBuyerPaymentService;
import com.yhsoft.buyer.service.IBuyerUserService;
import com.yhsoft.common.exception.BusinessException;
import com.yhsoft.common.vo.Result;
import com.yhsoft.wxprogram.utils.CommonUtil;
import com.yhsoft.wxprogram.utils.ConstantPropertiesUtils;
import com.yhsoft.wxprogram.utils.HttpClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 支付 服务实现类
 * </p>
 *
 * @author yyyyyyyh
 * @since 2023-09-26
 */
@Slf4j
@Service
public class BuyerPaymentServiceImpl extends ServiceImpl<BuyerPaymentMapper, BuyerPayment> implements IBuyerPaymentService {
    @Resource
    private IBuyerOrderService iBuyerOrderService;

    @Resource
    private IBuyerUserService iBuyerUserService;

    @Resource
    private CloseableHttpClient closeableHttpClient;

    @Override
    public Map<String, String> prepay(String orderId) {
        // 0. 校验订单状态
        BuyerOrder buyerOrder = iBuyerOrderService.getById(orderId);
        if (buyerOrder == null) {
            throw new BusinessException("订单不存在");
        }
        if (buyerOrder.getOrderStatus() != 1 && buyerOrder.getOrderStatus() != 5) {
            throw new BusinessException("该订单无法进行微信支付！");
        }

        // 1. 封装微信支付系统接口需要参数
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("appid", ConstantPropertiesUtils.APPID);
        paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
        String subject = "userID:" + buyerOrder.getUserId() + "下订单";
        paramMap.put("body", subject);
        paramMap.put("out_trade_no", buyerOrder.getOrderId());
        int i = new BigDecimal("0.01").multiply(new BigDecimal(100)).intValue();
        //int totalFee = buyerOrder.getPayablePrice().multiply(new BigDecimal(100)).intValue();
        paramMap.put("total_fee", String.valueOf(i));
        paramMap.put("spbill_create_ip", "58.216.180.30");
        // TODO: 设置回调地址
        paramMap.put("notify_url", ConstantPropertiesUtils.NOTIFYURL);
        paramMap.put("trade_type", "JSAPI");

        //openid
        BuyerUser buyerUser = iBuyerUserService.getById(buyerOrder.getUserId());

        if (null != buyerUser && !StringUtils.isEmpty(buyerUser.getOpenId())) {
            paramMap.put("openid", buyerUser.getOpenId());
        } else {
            paramMap.put("openid", "odo3j4q2KskkbbW-krfE-cAxUnzU1");
        }
        //3 使用HttpClient调用微信支付系统接口
        HttpClient client =
                new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
        //设置参数，xml格式
        try {
            client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY));
            client.setHttps(true);
            client.post();

            //4 调用微信支付系统接口之后，返回结果 prepay_id
            String xml = client.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);

            //5 封装需要数据-包含预付单标识 prepay_id
            Map<String, String> parameterMap = new HashMap<>();
            String prepayId = String.valueOf(resultMap.get("prepay_id"));
            String packages = "prepay_id=" + prepayId;
            parameterMap.put("appId", ConstantPropertiesUtils.APPID);
            parameterMap.put("nonceStr", resultMap.get("nonce_str"));
            parameterMap.put("package", packages);
            parameterMap.put("signType", "MD5");
            parameterMap.put("timeStamp", String.valueOf(System.currentTimeMillis()));
            String sign = WXPayUtil.generateSignature(parameterMap, ConstantPropertiesUtils.PARTNERKEY);

            //返回结果
            Map<String, String> result = new HashMap<>();
            result.put("timeStamp", parameterMap.get("timeStamp"));
            result.put("nonceStr", parameterMap.get("nonceStr"));
            result.put("signType", "MD5");
            result.put("paySign", sign);
            result.put("package", packages);

            //6 返回结果
            return result;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Map<String, String> queryPayStatus(String orderId) {
        //封装数据
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("appid", ConstantPropertiesUtils.APPID);
        paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);
        paramMap.put("out_trade_no", orderId);
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());

        //2、设置请求
        HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
        try {
            client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY));
            client.setHttps(true);
            client.post();

            //3 得到返回结果
            String xml = client.getContent();
            return WXPayUtil.xmlToMap(xml);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Map<String, Object> queryRefundStatus(String orderNo) {
        try {
            BuyerOrder buyerOrder = iBuyerOrderService.getById(orderNo);
            log.info("查询退款接口调用 ===> {}", orderNo);
            HashMap<String, Object> result = new HashMap<>();
            WechatPayHttpClientBuilder builder = CommonUtil.getWechatPayHttpClientBuilder();
            CloseableHttpClient httpClient = builder.build();
            //创建远程Get 请求对象
            HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/" + buyerOrder.getRefundNo());
            httpGet.setHeader("Accept", "application/json");
            //完成签名并执行请求
            CloseableHttpResponse response = httpClient.execute(httpGet);
            String bodyAsString = EntityUtils.toString(response.getEntity());
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                log.info("成功, 查询退款返回结果 = " + bodyAsString);
            } else if (statusCode == 204) {
                log.info("成功");
            } else {
                throw new RuntimeException("查询退款异常, 响应码 = " + statusCode + ", 查询退款返回结果 = " + bodyAsString);
            }
            result.put("body", bodyAsString);
            result.put("orderNo", orderNo);
            result.put("code", 200);
            return result;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Result<?> orderRefund(String orderNo) {
        try {
            BuyerOrder buyerOrder = iBuyerOrderService.getById(orderNo);
            WechatPayHttpClientBuilder builder = CommonUtil.getWechatPayHttpClientBuilder();
            CloseableHttpClient httpClient = builder.build();
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();
            ObjectNode rootNode = objectMapper.createObjectNode();
            rootNode.put("out_trade_no", orderNo);
            String refundOrderId = IdWorker.getIdStr();
            buyerOrder.setRefundNo(refundOrderId);
            iBuyerOrderService.updateById(buyerOrder);
            rootNode.put("out_refund_no", refundOrderId);
            rootNode.putObject("amount")
                    .put("refund",1)
                    .put("total", 1)
                    //.put("refund", JSONObject.toJSONString(0.01))
                    //.put("total", JSONObject.toJSONString(0.01))
                    .put("currency", "CNY");
            objectMapper.writeValue(bos, rootNode);

            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpPost);

            String result = EntityUtils.toString(response.getEntity());
            log.info("结果是：{}", result);
            return Result.success(result);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail("退款失败");
        }
    }
}
